const { FunctionModule, Notification, Recommendation, User, CourseCategory } = require('./model');
const { Op } = require('sequelize');

class SystemDao {
  // 功能模块相关操作
  
  // 创建功能模块
  async createFunctionModule(moduleData) {
    try {
      return await FunctionModule.create(moduleData);
    } catch (error) {
      throw new Error(`创建功能模块失败: ${error.message}`);
    }
  }

  // 获取所有功能模块
  async getFunctionModules(options = {}) {
    try {
      const { enabled } = options;
      
      const whereClause = {};
      if (enabled !== undefined) whereClause.enabled = enabled;

      return await FunctionModule.findAll({
        where: whereClause,
        order: [['sort', 'ASC'], ['created_at', 'ASC']]
      });
    } catch (error) {
      throw new Error(`获取功能模块列表失败: ${error.message}`);
    }
  }

  // 根据键值获取功能模块
  async getFunctionModuleByKey(key) {
    try {
      return await FunctionModule.findOne({ where: { key } });
    } catch (error) {
      throw new Error(`获取功能模块失败: ${error.message}`);
    }
  }

  // 更新功能模块
  async updateFunctionModule(id, updateData) {
    try {
      const [updatedRowsCount] = await FunctionModule.update(updateData, {
        where: { id }
      });
      
      if (updatedRowsCount === 0) {
        throw new Error('功能模块不存在');
      }
      
      return await FunctionModule.findByPk(id);
    } catch (error) {
      throw new Error(`更新功能模块失败: ${error.message}`);
    }
  }

  // 删除功能模块
  async deleteFunctionModule(id) {
    try {
      const deletedRowsCount = await FunctionModule.destroy({
        where: { id }
      });
      
      if (deletedRowsCount === 0) {
        throw new Error('功能模块不存在');
      }
      
      return true;
    } catch (error) {
      throw new Error(`删除功能模块失败: ${error.message}`);
    }
  }

  // 通知相关操作

  // 创建通知
  async createNotification(notificationData) {
    try {
      return await Notification.create(notificationData);
    } catch (error) {
      throw new Error(`创建通知失败: ${error.message}`);
    }
  }

  // 批量创建通知（给多个用户发送相同通知）
  async createBulkNotifications(userIds, notificationData) {
    try {
      const notifications = userIds.map(userId => ({
        ...notificationData,
        user_id: userId
      }));
      
      return await Notification.bulkCreate(notifications);
    } catch (error) {
      throw new Error(`批量创建通知失败: ${error.message}`);
    }
  }

  // 获取用户通知列表
  async getUserNotifications(userId, options = {}) {
    try {
      const { page = 1, limit = 10, status, type } = options;
      const offset = (page - 1) * limit;
      
      const whereClause = { user_id: userId };
      if (status) whereClause.status = status;
      if (type) whereClause.type = type;

      const { count, rows } = await Notification.findAndCountAll({
        where: whereClause,
        order: [['created_at', 'DESC']],
        limit: parseInt(limit),
        offset: parseInt(offset)
      });

      return {
        notifications: rows,
        total: count,
        page: parseInt(page),
        limit: parseInt(limit),
        totalPages: Math.ceil(count / limit)
      };
    } catch (error) {
      throw new Error(`获取用户通知列表失败: ${error.message}`);
    }
  }

  // 获取用户未读通知数量
  async getUnreadNotificationCount(userId) {
    try {
      return await Notification.count({
        where: {
          user_id: userId,
          status: 'unread'
        }
      });
    } catch (error) {
      throw new Error(`获取未读通知数量失败: ${error.message}`);
    }
  }

  // 标记通知为已读
  async markNotificationAsRead(id, userId) {
    try {
      const [updatedRowsCount] = await Notification.update(
        { 
          status: 'read',
          read_at: new Date()
        },
        {
          where: { id, user_id: userId }
        }
      );
      
      if (updatedRowsCount === 0) {
        throw new Error('通知不存在或无权限');
      }
      
      return true;
    } catch (error) {
      throw new Error(`标记通知已读失败: ${error.message}`);
    }
  }

  // 批量标记通知为已读
  async markNotificationsAsRead(ids, userId) {
    try {
      const [updatedRowsCount] = await Notification.update(
        { 
          status: 'read',
          read_at: new Date()
        },
        {
          where: { 
            id: { [Op.in]: ids },
            user_id: userId 
          }
        }
      );
      
      return updatedRowsCount;
    } catch (error) {
      throw new Error(`批量标记通知已读失败: ${error.message}`);
    }
  }

  // 删除通知
  async deleteNotification(id, userId) {
    try {
      const deletedRowsCount = await Notification.destroy({
        where: { id, user_id: userId }
      });
      
      if (deletedRowsCount === 0) {
        throw new Error('通知不存在或无权限');
      }
      
      return true;
    } catch (error) {
      throw new Error(`删除通知失败: ${error.message}`);
    }
  }

  // 推荐内容相关操作

  // 创建推荐内容
  async createRecommendation(recommendationData) {
    try {
      return await Recommendation.create(recommendationData);
    } catch (error) {
      throw new Error(`创建推荐内容失败: ${error.message}`);
    }
  }

  // 获取推荐内容列表
  async getRecommendations(options = {}) {
    try {
      const { page = 1, limit = 10, type, difficulty, category_id, is_featured, is_active } = options;
      const offset = (page - 1) * limit;
      
      const whereClause = {};
      if (type) whereClause.type = type;
      if (difficulty) whereClause.difficulty = difficulty;
      if (category_id) whereClause.category_id = category_id;
      if (is_featured !== undefined) whereClause.is_featured = is_featured;
      if (is_active !== undefined) whereClause.is_active = is_active;

      const { count, rows } = await Recommendation.findAndCountAll({
        where: whereClause,
        include: [{
          model: CourseCategory,
          as: 'courseCategory',
          required: false
        }],
        order: [['sort', 'ASC'], ['created_at', 'DESC']],
        limit: parseInt(limit),
        offset: parseInt(offset)
      });

      return {
        recommendations: rows,
        total: count,
        page: parseInt(page),
        limit: parseInt(limit),
        totalPages: Math.ceil(count / limit)
      };
    } catch (error) {
      throw new Error(`获取推荐内容列表失败: ${error.message}`);
    }
  }

  // 获取精选推荐内容
  async getFeaturedRecommendations(limit = 5) {
    try {
      return await Recommendation.findAll({
        where: {
          is_featured: true,
          is_active: true
        },
        include: [{
          model: CourseCategory,
          as: 'courseCategory',
          required: false
        }],
        order: [['sort', 'ASC'], ['created_at', 'DESC']],
        limit: parseInt(limit)
      });
    } catch (error) {
      throw new Error(`获取精选推荐内容失败: ${error.message}`);
    }
  }

  // 根据ID获取推荐内容
  async getRecommendationById(id) {
    try {
      return await Recommendation.findByPk(id, {
        include: [{
          model: CourseCategory,
          as: 'courseCategory',
          required: false
        }]
      });
    } catch (error) {
      throw new Error(`获取推荐内容失败: ${error.message}`);
    }
  }

  // 更新推荐内容
  async updateRecommendation(id, updateData) {
    try {
      const [updatedRowsCount] = await Recommendation.update(updateData, {
        where: { id }
      });
      
      if (updatedRowsCount === 0) {
        throw new Error('推荐内容不存在');
      }
      
      return await this.getRecommendationById(id);
    } catch (error) {
      throw new Error(`更新推荐内容失败: ${error.message}`);
    }
  }

  // 增加查看次数
  async incrementRecommendationViewCount(id) {
    try {
      const recommendation = await this.getRecommendationById(id);
      if (!recommendation) {
        throw new Error('推荐内容不存在');
      }

      return await this.updateRecommendation(id, {
        view_count: recommendation.view_count + 1
      });
    } catch (error) {
      throw new Error(`增加查看次数失败: ${error.message}`);
    }
  }

  // 删除推荐内容
  async deleteRecommendation(id) {
    try {
      const deletedRowsCount = await Recommendation.destroy({
        where: { id }
      });
      
      if (deletedRowsCount === 0) {
        throw new Error('推荐内容不存在');
      }
      
      return true;
    } catch (error) {
      throw new Error(`删除推荐内容失败: ${error.message}`);
    }
  }
}

module.exports = new SystemDao();
